﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "CmdCreateStructurePlateHole.h"

#include "IInstanceType.h"
#include "StructureCmdIds.h"
#include "IEditMode.h"
#include "StructureInstancePresetParameterUtils.h"
#include "IFamily.h"
#include "StructureFamilyUtils.h"
#include "IUserTransaction.h"
#include "StructureCmdParamIds.h"
#include "ICommandManager.h"
#include "CommandParameters.h"
#include "IUiDocument.h"
#include "UserTransactionGroupUtils.h"
#include "CmdStatusUtils.h"
#include "IStructurePlateHoleEditModeBehavior.h"
#include "StructureEditModeTypes.h"
#include "InteractivePicker.h"
#include "StructurePlateHolePickFilter.h"
#include "StructureDefaultFamilyNames.h"
#include "GbmpBuiltInCategoryUniIdentitiesNew.h"
#include "UiCommonDialog.h"
#include "IModelView.h"
#include "GbmpModelViewTypes.h"
#include "GmUiStructureCommandRegister.h"
#include "UiDocumentViewUtils.h"
#include "IGraphicsNodeReference.h"
#include "GbmpGroupUtils.h"
#include "IMainWindow.h"
#include "IRibbon.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

REGISTER_GM_COMMAND(CmdCreateStructurePlateHole)

CmdCreateStructurePlateHole::CmdCreateStructurePlateHole(): GbmpCommandBase(ID_CMD_CREATE_STRUCTURE_PLATE_HOLE)
{
}

bool CmdCreateStructurePlateHole::IsEnabled() const
{
    CMD_ONLY_ENABLE_IN_PROJECT_ENVIRONMENT
}

bool CmdCreateStructurePlateHole::IsVisible() const
{
    CMD_ONLY_VISIBLE_IN_PROJECT_ENVIRONMENT
}

OwnerPtr<IAction> CmdCreateStructurePlateHole::ExecuteCommand(const CommandParameters& cmdParams)
{
    if (!CheckRunTimeEnvironment())
    {
        return nullptr;
    }
    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IUiDocument* pUIDoc = UiDocumentViewUtils::GetCurrentUiDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUIDoc, L"pUIDoc为空",L"GDMPLab",L"2024-03-30");

    // 创建内建楼板/筏形板洞族
    StructureFamilyUiUtils::FamilyCreators defaultFamilyCreators = this->GetDefaultFamilyCreators();
    StructureFamilyUiUtils::CreateFamilies(pDoc, defaultFamilyCreators);

    // 获取新创建实例的族名称、实例类型
    std::wstring familyName;
    std::wstring instanceType;
    {
        // 从命令参数读取
        auto itor = cmdParams.find(ID_CMD_PARAM_FAMILY_NAME);
        if (itor != cmdParams.end())
        {
            familyName = itor->second.AsWString();
        }
        itor = cmdParams.find(ID_CMD_PARAM_INSTANCE_TYPE);
        if (itor != cmdParams.end())
        {
            instanceType = itor->second.AsWString();
        }
    }
    if (familyName.empty() || instanceType.empty())
    {
        StructureInstancePresetParameterUtils::GetPresetFamilyNameAndInstanceType(pDoc, this->GetCategory(),
            this->GetCategorySecondKey(), familyName, instanceType);
    }
    if (familyName.empty())
    {
        familyName = GetDefaultFamilyName();
    }
    const IFamily* pFamily = IFamily::GetFamilyByName(pDoc, familyName);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamily, L"pFamily为空",L"GDMPLab",L"2024-03-30");

    if (instanceType.empty())
    {
        bool bOk = StructureFamilyUtils::GetFirstInstanceType(pFamily, instanceType);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"GetFirstInstanceType失败",L"GDMPLab",L"2024-03-30");
    }
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!instanceType.empty(), L"instanceType为空",L"GDMPLab",L"2024-03-30");

    const IInstanceType* pInstanceType = pFamily->GetInstanceTypeByName(instanceType);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstanceType, L"pInstanceType为空",L"GDMPLab",L"2024-03-30");

    this->SetFamilyIdAndInstanceTypeId(pFamily->GetElementId(), pInstanceType->GetElementId());

    const IMainWindow *pMainWindow = IMainWindow::GetMainWindow();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pMainWindow, L"pMainWindow为空",L"GDMPLab",L"2024-03-30");
    IRibbon *pRibbon = pMainWindow->GetRibbon();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pRibbon, L"pRibbon为空",L"GDMPLab",L"2024-03-30");
    pRibbon->SetCustomHighLightControl(std::vector<std::wstring>{GetCommandId()});
    ElementId hostInstanceId = GetPickedResultId();
    if (hostInstanceId.GetIsValidId())
    {
        int groupId;
        UserTransactionGroupUtils::Start(pDoc, GBMP_TR(L"创建洞口轮廓实例"), groupId);
        OwnerPtr<IUserTransaction> ut = IUserTransaction::Create(pDoc, GBMP_TR(L"开始绘制洞口"));
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(ut, L"ut为空",L"GDMPLab",L"2024-03-30");
        {
            IEditMode* pProfileEditMode = IEditMode::Get(pDoc, StructureEditModeTypes::StructurePlateHoleModeType);
            if (pProfileEditMode == nullptr)
            {
                pProfileEditMode = IEditMode::Create(pDoc, IStructurePlateHoleEditModeBehavior::Create());
            }
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pProfileEditMode != nullptr, L"pTracesEditMode为空",L"GDMPLab",L"2024-03-30");
            IStructurePlateHoleEditModeBehavior* pProfileEDBehavior = quick_cast<IStructurePlateHoleEditModeBehavior>(pProfileEditMode->GetEditModeBehavior());
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pProfileEDBehavior, L"pProfileEDBehavior为空！",L"GDMPLab",L"2024-03-30");

            pProfileEDBehavior->SetEditingFamilyId(m_familyId);
            pProfileEDBehavior->SetEditingInstanceTypeId(m_instanceTypeId);
            pProfileEDBehavior->SetHostId(hostInstanceId);
            pProfileEditMode->StartEditing(pDoc, ElementId::InvalidID, true, false);
        }
        bool bCommit = ut->Commit();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bCommit, L"事务提交失败",L"GDMPLab",L"2024-03-30");

        pUIDoc->UpdateView();
        // 启动画直轮廓线的命令
        ICommandManager* pCommandManager = ICommandManager::Get();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pCommandManager, L"pCommandManager为空",L"GDMPLab",L"2024-03-30");
        pCommandManager->SendCommand(ID_CMD_STRUCTURE_DRAW_STRAIGHT_PROFILE);
    }
    pRibbon->SetCustomHighLightControl(std::vector<std::wstring>{});
    return nullptr;
}

bool CmdCreateStructurePlateHole::SetFamilyIdAndInstanceTypeId(ElementId familyId, ElementId instanceTypeId)
{
    if (m_familyId.HasSameValue(familyId) && m_instanceTypeId.HasSameValue(instanceTypeId))
    {
        return true;
    }

    m_familyId = familyId;
    m_instanceTypeId = instanceTypeId;

    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IUserTransaction> opTransaction = IUserTransaction::Create(pDoc, GBMP_TR(L"保存当前创建实例的族类型到预设参数"), true);

    bool bOk = StructureInstancePresetParameterUtils::SetPresetInstanceType(pDoc, this->GetCategory(), this->GetCategorySecondKey(),
        instanceTypeId);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"SetPresetInstanceType失败",L"GDMPLab",L"2024-03-30");

    opTransaction->Commit();

    return true;
}

ElementId CmdCreateStructurePlateHole::GetPickedResultId() const
{
    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_UNLESS(pDoc, ElementId::InvalidID, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    InteractivePicker::PickerResult pickerResult;
    Vector3d pickedPt;
    GraphicsNodeReferenceOwnerPtrVector nodeReferences;
    OwnerPtr<StructurePlateHolePickFilter> pPickFilter = NEW_AS_OWNER_PTR(StructurePlateHolePickFilter, pDoc);
    pickerResult = InteractivePicker::Select(false, false, TransferOwnership(pPickFilter), L"选择将要放置板洞的板", L"选择将要放置板洞的板", pickedPt, nodeReferences);
    if (pickerResult.FinishStatus == InteractivePicker::PickerFinishStatus::Successful)
    {
        return nodeReferences[0]->GetElementId();
    }
    return ElementId::InvalidID;
}

StructureFamilyUiUtils::FamilyCreators CmdCreateStructurePlateHole::GetDefaultFamilyCreators() const
{
    StructureFamilyUiUtils::FamilyCreators defaultFamilyCreators
    {
        { DEFAULT_PLATE_STRUCTURE_HOLE_FAMILY_NAME, BuiltInStructureFamilies::CreateBuiltInPlateHoleFamilyDocument }
    };

    return defaultFamilyCreators;
}

std::wstring CmdCreateStructurePlateHole::GetDefaultFamilyName() const
{
    return DEFAULT_PLATE_STRUCTURE_HOLE_FAMILY_NAME;
}

UniIdentity CmdCreateStructurePlateHole::GetCategory() const
{
    return BuiltInCategoryUniIdentities::BICU_STRUCTURE_PLATE_HOLE;
}

bool CmdCreateStructurePlateHole::CheckRunTimeEnvironment() const
{
    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IModelView* pModelView = UiDocumentViewUtils::GetCurrentModelView();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");

    const std::wstring& viewType = pModelView->GetUserDataId();

    if (PlanViewType != viewType && View3DViewType != viewType)
    {
        UiCommonDialog::ShowMessageBox(GBMP_TR(L"绘制板洞"), GBMP_TR(L"此视图下不支持绘制板洞"), (int)UiCommonDialog::ButtonType::OK);
        return false;
    }
    IEditMode* pTopEditMode = IEditMode::GetTopActiveEditMode(pDoc);
    if (pTopEditMode != nullptr && pTopEditMode->GetEditModeType() != GbmpGroupUtils::GroupEditModeType)
    {
        UiCommonDialog::ShowMessageBox(GBMP_TR(L"警告"), GBMP_TR(L"正在编辑板洞！不能重新创建实例"), (int)UiCommonDialog::ButtonType::OK);
        return false;
    }
    return true;
}
